package com.zmn.mcc.business.impl.dpermit.company;

import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.manager.common.database.annotation.ReadOnlyConnection;
import com.zmn.mcc.business.interfaces.dpermit.company.DpermitCompanyBService;
import com.zmn.mcc.common.constant.DpermitConsts;
import com.zmn.mcc.manager.utils.DpermitUtil;
import com.zmn.mcc.model.dto.dpermit.DpermitBaseDO;
import com.zmn.mcc.model.dto.dpermit.DpermitCountDO;
import com.zmn.mcc.model.dto.dpermit.DpermitSimpleDO;
import com.zmn.mcc.model.entity.organize.McOrganize;
import com.zmn.mcc.services.interfaces.organize.OrganizeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author heguanghua
 * @since 2020/05/26 17:42
 */
@Service
public class DpermitCompanyBServiceImpl implements DpermitCompanyBService {
    protected Logger logger = LoggerFactory.getLogger(DpermitCompanyBServiceImpl.class);

    @Resource
    private OrganizeService organizeService;

    // region 取得全部平台/大区/子公司/服务商列表，平台、大区和子公司并列

    @Override
    @ReadOnlyConnection
    public List<DpermitSimpleDO> listOrganizeAndDpermitChecked(Integer status, List<? extends DpermitBaseDO> dpermitOrganizes) {

        List<DpermitSimpleDO> items = new ArrayList<>();

        // 组织ID和简单组织对象的映射关系
        Map<Integer, DpermitSimpleDO> map = new HashMap<>();
        Map<Integer, DpermitBaseDO> dpertmitMap = new LinkedHashMap<>();
        for(DpermitBaseDO dpermit: dpermitOrganizes) {
            dpertmitMap.put(dpermit.getDataId(), dpermit);
        }

        // 平台/大区/子公司列表
        List<McOrganize> organizes = organizeService.listAboveByLevel(DpermitConsts.ORGANIZE_LEVEL_SUB, status);
        for(McOrganize organize: organizes) {

            // 防止数据错误抛出异常
            if(organize.getLevel() == null) {
                continue;
            }

            // 简单组织对象
            DpermitSimpleDO simple = this.parseToDpermitSimpleDO(organize);

            // 子公司加入映射关系map
            if(organize.getLevel().intValue() == DpermitConsts.ORGANIZE_LEVEL_SUB) {
                map.put(simple.getDataId(), simple);
            }

            // 选中已分配
            if(CollectionUtil.isNotNullOrEmpty(dpertmitMap) && dpertmitMap.containsKey(simple.getDataId())) {
                simple.setChecked(true);
            }

            // 平台/大区/子公司加入主列表
            if(organize.getLevel().intValue() <= DpermitConsts.ORGANIZE_LEVEL_SUB) {
                items.add(simple);
            }
        }

        /**
         * 服务商加入子公司的子集
         * 都是已分配的
         */
        for(DpermitBaseDO dpermit: dpertmitMap.values()) {
            if(dpermit.getDataLevel().intValue() != DpermitConsts.ORGANIZE_LEVEL_GRANDSON) {
                continue;
            }
            DpermitSimpleDO simple = map.get(dpermit.getDataParentId());
            if(simple == null) {
                continue;
            }
            simple.getSubors().add(DpermitUtil.parseToDpermitSimpleDO(dpermit));
        }

        return items;
    }
    // endregion

    // region 取得全部平台/大区/子公司的层级列表

    @Override
    @ReadOnlyConnection
    public List<DpermitSimpleDO> listOrganizeTreeAndDpermitChecked(Integer status, List<Integer> dpermitIds, List<DpermitCountDO> dpermitCounts) {

        List<DpermitSimpleDO> items = new ArrayList<>();

        // 组织ID和简单组织对象的映射关系
        Map<Integer, DpermitSimpleDO> map = new HashMap<>();
        Map<Integer, DpermitSimpleDO> subMap = new HashMap<>();
        Map<Integer, Integer> countMap = new HashMap<>();
        for(DpermitCountDO dpermitCount: dpermitCounts) {
            countMap.put(dpermitCount.getDataId(), dpermitCount.getCount());
        }

        // 平台/大区/子公司列表
        List<McOrganize> organizes = organizeService.listAboveByLevel(DpermitConsts.ORGANIZE_LEVEL_SUB, status);
        for(McOrganize organize: organizes) {

            // 防止数据错误抛出异常
            if(organize.getLevel() == null) {
                continue;
            }

            // 简单组织对象
            DpermitSimpleDO simple = this.parseToDpermitSimpleDO(organize);

            // 平台/大区加入映射关系map
            if(organize.getLevel().intValue() <= DpermitConsts.ORGANIZE_LEVEL_REGION) {
                map.put(simple.getDataId(), simple);
            } else if(organize.getLevel().intValue() == DpermitConsts.ORGANIZE_LEVEL_SUB) {
                subMap.put(simple.getDataId(), simple);
            }

            // 选中已分配
            if(CollectionUtil.isNotNullOrEmpty(dpermitIds) && dpermitIds.contains(simple.getDataId())) {
                simple.setChecked(true);
            }

            // 平台加入主列表
            if(organize.getLevel().intValue() == DpermitConsts.ORGANIZE_LEVEL_PLAT) {
                items.add(simple);
            }
            // 大区/子公司上级组织的子集
            else if(organize.getLevel().intValue() >= DpermitConsts.ORGANIZE_LEVEL_REGION) {
                DpermitSimpleDO parent = map.get(simple.getParentId());
                if(parent != null) {
                    parent.getSubors().add(simple);
                }
            }
        }

        /**
         * 特殊处理子公司的下级全选状态
         * 子公司选中且没有下级服务商则视为全选
         */
        for(DpermitSimpleDO simple: subMap.values()) {
            int count = Optional.ofNullable(countMap.get(simple.getDataId())).orElse(0);
            if(count > 0) {
                simple.setChecked(true);
                simple.setLowerSubCount(count);
                simple.setSubAll(false);
            }
        }

        /**
         * 检查并处理简单数据对象选中状态
         * 下级部分选中则上级选中，下级全部选中则对上级标识
         */
        DpermitUtil.checkSelected(items, false);

        return items;
    }

    // endregion


    /**
     * 转换为简单数据权限对象
     * @param organize
     * @return
     */
    private DpermitSimpleDO parseToDpermitSimpleDO(McOrganize organize) {
        if(organize == null) {
            return null;
        }
        DpermitSimpleDO simple = new DpermitSimpleDO();
        simple.setDataId(organize.getOrgId());
        simple.setDataName(organize.getOrgName());
        simple.setParentId(organize.getParentId());
        simple.setStatus(organize.getStatus());
        simple.setLevel(organize.getLevel());
        return simple;
    }
}
